import math
import random

Alpha = 1
Beta = 3


# 公式系数
def func(pheromone, yita):
    rate = pheromone ** Alpha * yita ** Beta
    return rate


def yita(distance):  # 启发式函数
    yita = 1 / distance
    return yita


def choicerate(ants, map):
    sum = 0
    rate = []
    for place in list((set(ants.quest.startplace) | set(ants.quest.endplace)) - set(ants.tabu)):
        sum += func(map.phromone(ants.place, place), yita(map.distance(ants.place, place)))
    if sum < math.e ** -20 :
        rate = random.choice(list((set(ants.quest.startplace) | set(ants.quest.endplace)) - set(ants.tabu)))
    else:
        for place in list((set(ants.quest.startplace) | set(ants.quest.endplace)) - set(ants.tabu)):
            rate += [func(map.phromone(ants.place, place), yita(map.distance(ants.place, place))) / sum]
    return rate


def random_pick(some_list, probabilities):
    if isinstance(probabilities,str):
        item = probabilities
    else:
        x = random.uniform(0, 1)
        cumulative_probability = 0.0
        for item, item_probability in zip(some_list, probabilities):
            cumulative_probability += item_probability#有很低概率出问题
            if x < cumulative_probability: break
    return item


class Ants:
    def __init__(self, volume, volcity, quest):
        self.volume = volume
        self.volcity = volcity
        self.quest = quest
        self.load = 0
        self.place = []
        self.route = []
        self.tabu = []  # 禁忌表

    def upload(self):
        for quest in self.quest:
            if self.place in quest.startplace and self.load + quest.task < self.volume:
                self.load += quest.task
                self.updatetabu(self.place)

    def download(self):
        for quest in self.quest:
            if self.place in quest.endplace and self.load > quest.task:
                self.load -= quest.task
                quest.complete()
                self.updatetabu(self.place)

    def move(self, targetplace):
        self.place = targetplace
        self.route += targetplace

    def updatetabu(self, place):
        self.tabu += place

    def iscomplete(self):
        for quest in self.quest:
            if quest.state is False:return False
        return True

